import gui
import sys
import wx
import os
from helper import invoke
import controller
import wx.lib.newevent
import threading

class SimulationView(gui.MainDialog):
    
    SIMULATION_STARTED = 0
    SIMULATION_STOPPED = 1
    SIMULATION_ABOUT_TO_STOP = 2
    
    class MessageWindow:
        def __init__(self, size):
            self._size = size
            self._content = []
            self._lock = threading.Lock()
        
        def append(self, msg):
            with self._lock:
                if self._size == len(self._content):
                    self._content.pop(0)
                self._content.append(msg)
            
        def __str__(self):
            str = ""
            with self._lock:
                for msg in self._content:
                    str += msg
            return str
        
        def __len__(self):
            with self._lock:
                l = len(self._content)
            return l
    
    def __init__(self):
        gui.MainDialog.__init__(self, None, -1, "")
        self._controller = None
        self._msg_win = SimulationView.MessageWindow(50)
        sys.stdout = self
        self.SetState(SimulationView.SIMULATION_STOPPED)
        self._EnableEvents()
        self._udpate_status_lock = threading.Lock()
      
    def _EnableEvents(self):
        wx.EVT_CLOSE(self, self._OnClose)
        wx.EVT_BUTTON(self, self.cloth_params_button.GetId(), self._SpecifyCloth)
        wx.EVT_BUTTON(self, self.commands_button.GetId(), self._SpecifyCommands)
        wx.EVT_BUTTON(self, self.dir_button.GetId(), self._SpecifyOutDir)
        wx.EVT_BUTTON(self, self.movie_button.GetId(), self._CreateMovie)
        wx.EVT_BUTTON(self, self.start_button.GetId(), self._StartSimulation)
        wx.EVT_BUTTON(self, self.stop_button.GetId(), self._StopSimulation)
            
    def _OnClose(self, event):
        wx.Exit()
    
    def _UpdateStatus(self):
        self.status.SetValue(str(self._msg_win))
        self.status.ScrollLines(len(self._msg_win))
    
    def write(self, msg):
        self._msg_win.append(msg)
        with self._udpate_status_lock:
            self._UpdateStatus()
        
    def SetController(self, controller):
        self._controller = controller
    
    def SetMinorTitle(self, title):
        self.SetTitle("Cloth simulation - "+str(title))
    
    def SetState(self, state):
        if state == SimulationView.SIMULATION_STOPPED:
            self.cloth_params_button.Enable()
            self.commands_button.Enable()
            self.movie_button.Enable()
            self.dir_button.Enable()
            self.start_button.Enable()
            self.stop_button.Disable()
        elif state == SimulationView.SIMULATION_STARTED:
            self.cloth_params_button.Disable()
            self.commands_button.Disable()
            self.movie_button.Disable()
            self.dir_button.Disable()
            self.start_button.Disable()
            self.stop_button.Enable()
        elif state == SimulationView.SIMULATION_ABOUT_TO_STOP:
            self.cloth_params_button.Disable()
            self.commands_button.Disable()
            self.movie_button.Disable()
            self.dir_button.Disable()
            self.start_button.Disable()
            self.stop_button.Disable()
    
    def SetClothParamsFileName(self, file_name):
        self.cloth_params_file_name.SetValue(file_name)
    
    def SetCommandsFileName(self, file_name):
        self.commands_file_name.SetValue(file_name)
    
    def SetOutputDirectoryName(self, dir_name):
        self.out_dir_name.SetValue(dir_name)
    
    def _InvokeController(self, method, *args):
        return invoke(self._controller, method, args)
    
    def _SpecifyCloth(self, event):
        dlg = wx.FileDialog(self, message="Specify cloth simulation parameters file...", \
                            defaultDir = os.getcwd(), defaultFile = "", style = wx.OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            self._InvokeController(controller.SimulationController.SetClothParams, dlg.GetPath())
                   
    
    def _SpecifyCommands(self, event):
        dlg = wx.FileDialog(self, message="Specify commands file...", \
                            defaultDir = os.getcwd(), defaultFile = "", style = wx.OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            self._InvokeController(controller.SimulationController.SetCommandList, dlg.GetPath())
    
    def _SpecifyOutDir(self, event):
        dlg = wx.DirDialog(self, message="Specify output directory...", \
                            defaultPath = os.getcwd(), style = wx.OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            self._InvokeController(controller.SimulationController.SetOutDir, dlg.GetPath())
    
    def _StartSimulation(self, event):
        self._InvokeController(controller.SimulationController.StartSimulation, [])
    
    def _StopSimulation(self, event):
        self._InvokeController(controller.SimulationController.StopSimulation, [])
    
    def _CreateMovie(self, event):
        self._InvokeController(controller.SimulationController.MakeMovie, [])
